/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import me.zhengjie.constant.ConstantUtils;
import me.zhengjie.exception.CommonUtilException;
import me.zhengjie.modules.system.domain.DisChangeApply;
import me.zhengjie.modules.system.domain.DisPartner;
import me.zhengjie.modules.system.domain.DisPartnerUser;
import me.zhengjie.modules.system.repository.DisChangeApplyRepository;
import me.zhengjie.modules.system.service.DisChangeApplyService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.apply.ApplyWorkOrderFactory;
import me.zhengjie.modules.system.service.dto.DisChangeApplyDto;
import me.zhengjie.modules.system.service.dto.DisChangeApplyQueryCriteria;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.modules.system.service.mapstruct.DisChangeApplyMapper;
import me.zhengjie.modules.web.service.mybatisplus.IDisPartnerPlusService;
import me.zhengjie.modules.web.service.mybatisplus.IDisPartnerUserPlusService;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 王宇
 * @website https://el-admin.vip
 * @description 服务实现
 * @date 2023-12-29
 **/
@Service
@RequiredArgsConstructor
public class DisChangeApplyServiceImpl implements DisChangeApplyService {

    private final DisChangeApplyRepository disChangeApplyRepository;
    private final DisChangeApplyMapper disChangeApplyMapper;

    @Autowired
    ApplyWorkOrderFactory applyWorkOrderFactory;

    @Autowired
    private IDisPartnerPlusService disPartnerPlusService;

    @Autowired
    private IDisPartnerUserPlusService disPartnerUserPlusService;

    @Autowired
    private UserService userService;

    @Override
    public Map<String, Object> queryAll(DisChangeApplyQueryCriteria criteria, Pageable pageable) {
        Page<DisChangeApply> page = disChangeApplyRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(disChangeApplyMapper::toDto));
    }

    @Override
    public List<DisChangeApplyDto> queryAll(DisChangeApplyQueryCriteria criteria) {
        return disChangeApplyMapper.toDto(disChangeApplyRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public DisChangeApplyDto findById(Long applyId) {
        DisChangeApply disChangeApply = disChangeApplyRepository.findById(applyId).orElseGet(DisChangeApply::new);
        ValidationUtil.isNull(disChangeApply.getApplyId(), "DisChangeApply", "applyId", applyId);
        return disChangeApplyMapper.toDto(disChangeApply);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DisChangeApplyDto create(DisChangeApply resources) {
        //1：身份绑定课程2：身份产品分润变更3：门票数量变更4：初始门票设置5：从属关系变更6：身份变更
        Integer applyType = resources.getApplyType();
        if (Objects.isNull(applyType)) {
            throw new CommonUtilException("缺少参数");
        }
        return disChangeApplyMapper.toDto(disChangeApplyRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DisChangeApply resources) {
        DisChangeApply disChangeApply = disChangeApplyRepository.findById(resources.getApplyId()).orElseGet(DisChangeApply::new);
        ValidationUtil.isNull(disChangeApply.getApplyId(), "DisChangeApply", "id", resources.getApplyId());
        disChangeApply.copy(resources);
        disChangeApplyRepository.save(disChangeApply);
    }

    /**
     * 审批
     *
     * @param resources
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approve(DisChangeApply resources) {
        if(resources.getApplyId() == null){
            throw new CommonUtilException("工单ID不能为空！");
        }
        DisChangeApply disChangeApply = disChangeApplyRepository.findById(resources.getApplyId()).orElseGet(DisChangeApply::new);
        if (ObjectUtil.isEmpty(disChangeApply)) {
            throw new CommonUtilException("工单不存在！");
        }

        if (disChangeApply.getApplyStatus() != 0) {
            throw new CommonUtilException("工单已审批，无需重复审批！");
        }
        disChangeApply.copy(resources);
        DisChangeApplyDto disChangeApplyDto = disChangeApplyMapper.toDto(disChangeApplyRepository.save(disChangeApply));
        if (resources.getApplyStatus() != 1) {
            return;
        }
        applyWorkOrderFactory.getApplyType(disChangeApply.getApplyType()).execute(disChangeApplyDto);

    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long applyId : ids) {
            disChangeApplyRepository.deleteById(applyId);
        }
    }

    @Override
    public void download(List<DisChangeApplyDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DisChangeApplyDto disChangeApply : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("申请类型", disChangeApply.getApplyType());
            map.put("申请类型描述", disChangeApply.getApplyTypeDesc());
            map.put("申请人", disChangeApply.getApplyUser());
            map.put("提交时间", disChangeApply.getCreateTime());
            map.put("更新时间", disChangeApply.getUpdateTime());
            map.put("更新人", disChangeApply.getUpdateUser());
            map.put("申请状态，0：提交申请，1：成功，2：失败", disChangeApply.getApplyStatus());
            map.put("拒绝原因", disChangeApply.getRefuseMsg());
            map.put("镜像", disChangeApply.getMirrorImage());
            map.put("申请内容", disChangeApply.getApplyContent());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<UserDto> managers() {

        List<UserDto> respList = new ArrayList<>();
        LambdaQueryWrapper<DisPartner> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DisPartner::getPartnerStatus, ConstantUtils.Valid);
        List<DisPartner> list = disPartnerPlusService.list(wrapper);
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(s -> {
                UserDto userDto = null;
                try {
                    userDto = userService.findByMobile(s.getMobile());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (Objects.nonNull(userDto)) {
                    respList.add(userDto);
                }
            });
        }
        List<DisPartnerUser> userList = disPartnerUserPlusService.list();
        if (!CollectionUtils.isEmpty(userList)) {
            userList.forEach(s -> {
                UserDto userDto = null;
                try {
                    userDto = userService.findByMobile(s.getMobile());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (Objects.nonNull(userDto)) {
                    respList.add(userDto);
                }
            });
        }
        if (CollectionUtils.isEmpty(respList)) {
            return respList;
        }
        return respList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(UserDto::getId))), ArrayList::new));
    }

}